package za.org.jcicada.genss;

import java.io.Serializable;
import java.net.URI;
import java.net.URISyntaxException;

/**
 * URN class for service names. Ensures that only valid names can be created and
 * are immutable.
 * 
 * @author rcrida
 */
public class ServiceURN implements Serializable {

    /** Serial version ID */
    private static final long serialVersionUID = 1L;

    /** Identifying services URNs */
    public static final String URN_SERVICE = "service";
    
    /** The system URN */
    private SystemURN systemURN;
    
    /** The actual URN is stored in a URI */
    private final URI serviceURI;

    // public ServiceURN(URI serviceURI) throws URISyntaxException {
    // }
    
    public ServiceURN(String urn) throws URISyntaxException {
        serviceURI = new URI(urn);
        validateURI();
    }

    /**
     * Construct a service URN
     * 
     * @param systemURN the name of the system
     * @param iface the interface name of the service
     * @throws URISyntaxException
     */
    public ServiceURN(SystemURN systemURN, String iface) throws URISyntaxException {
        this(URN_SERVICE, systemURN, iface);
    }

    /**
     * Construct an interface service URN
     * 
     * @param iface the interface name of the service
     * @param systemURN the name of the system
     * @param service the name of the service
     * @throws URISyntaxException
     */
    protected ServiceURN(String iface, SystemURN systemURN, String service) throws URISyntaxException {
        serviceURI = new URI(String.format("%s/%s/%s", iface, systemURN.getSystemName(), service));
        validateURI();
    }
    
    public String getService() {
    	return serviceURI.toString().split("/")[0];
    }
    
    public SystemURN getSystemURN() {
        return systemURN;
    }
    
    public String getInterface() {
    	return serviceURI.toString().split("/")[2];
    }
    
    /**
     * Validate the serviceURI to ensure that it is correct.
     * @throws URISyntaxException
     */
    private void validateURI() throws URISyntaxException {
        if (serviceURI.getScheme() != null) {
            String message = String.format("Project URN scheme must be null (%s) in urn %s", serviceURI.getScheme(), serviceURI.toString());
            throw new URISyntaxException(serviceURI.toString(), message);
        }
        
        if (serviceURI.getAuthority() != null) {
            String message = String.format("Project URN authority component must be null (%s) in urn %s", serviceURI.getAuthority(), serviceURI.toString());
            throw new URISyntaxException(serviceURI.toString(), message);
        }       
        
        if (serviceURI.getQuery() != null) {
            String message = String.format("Project URN query part must be null (%s) in urn %s", serviceURI.getQuery(), serviceURI.toString());
            throw new URISyntaxException(serviceURI.toString(), message);
        }   
        
        if (serviceURI.getFragment() != null) {
            String message = String.format("Project URN fragment part must be null (%s) in urn %s", serviceURI.getFragment(), serviceURI.toString());
            throw new URISyntaxException(serviceURI.toString(), message);
        }
        
        String[] split = serviceURI.toString().split("/");
        if (split.length != 3) {
            String message = String.format("Project URN must have 3 parts (%d) in urn %s", split.length, serviceURI.toString());
            throw new URISyntaxException(serviceURI.toString(), message);
        }
    
        systemURN = new SystemURN(serviceURI.toString().split("/")[1]);

    }

    @Override
    public String toString() {
        return serviceURI.toString();
    }

    @Override
    public boolean equals(Object aOther) {
        if (this == aOther)
            return true;
        if (!(aOther instanceof ServiceURN))
            return false;
        ServiceURN other = (ServiceURN) aOther;
        return serviceURI.equals(other.serviceURI);
    }

    @Override
    public int hashCode() {
        return serviceURI.hashCode();
    }
}
